/*
package com.meihuayishu.backend.service.impl;

import com.meihuayishu.backend.dto.*;
import com.meihuayishu.backend.entity.User;
import com.meihuayishu.backend.repository.UserRepository;
import com.meihuayishu.backend.service.AuthService;
import com.meihuayishu.backend.util.JwtUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
@RequiredArgsConstructor
@Slf4j
public class AuthServiceImpl implements AuthService {
    
    private final UserRepository userRepository;
    private final JwtUtil jwtUtil;
    private final PasswordEncoder passwordEncoder;
    private final RedisTemplate<String, String> redisTemplate;
    
    private static final String SMS_CODE_PREFIX = "sms:code:";
    private static final String TOKEN_BLACKLIST_PREFIX = "blacklist:token:";
    private static final String USER_TOKENS_PREFIX = "user:tokens:";
    
    @Override
    public SendCodeResponse sendVerificationCode(SendCodeRequest request) {
        try {
            // TODO: 实际项目中需要验证图形验证码
            log.info("验证图形验证码: {}", request.getCaptcha().getToken());
            
            // 检查发送频率限制
            String rateKey = "rate:" + request.getPhone();
            if (redisTemplate.hasKey(rateKey)) {
                throw new RuntimeException("发送过于频繁，请稍后再试");
            }
            
            // 生成6位验证码
            String code = String.format("%06d", new Random().nextInt(999999));
            
            // 存储验证码到Redis，有效期5分钟
            String codeKey = SMS_CODE_PREFIX + request.getPhone() + ":" + request.getType();
            redisTemplate.opsForValue().set(codeKey, code, 300, TimeUnit.SECONDS);
            
            // 设置发送频率限制，60秒内不能重复发送
            redisTemplate.opsForValue().set(rateKey, "1", 60, TimeUnit.SECONDS);
            
            // TODO: 调用短信服务发送验证码
            log.info("发送验证码到 {}: {}", maskPhone(request.getPhone()), code);
            
            return SendCodeResponse.builder()
                    .expiresIn(300)
                    .interval(60)
                    .codeLength(6)
                    .build();
        } catch (Exception e) {
            log.error("发送验证码失败: {}", e.getMessage());
            throw new RuntimeException("发送验证码失败: " + e.getMessage());
        }
    }
    
    @Override
    public UserAuthResponse register(UserRegistrationRequestV2 request) {
        try {
            // 验证验证码
            validateVerificationCode(request.getPhone(), "REGISTER", request.getVerificationCode());
            
            // 检查手机号是否已注册
            if (userRepository.findByPhone(request.getPhone()).isPresent()) {
                throw new RuntimeException("手机号已注册");
            }
            
            // 创建用户
            User user = new User();
            user.setPhone(request.getPhone());
            user.setPassword(passwordEncoder.encode(request.getPassword()));
            user.setNickname(request.getNickname() != null ? request.getNickname() : "易学新手");
            user.setLevel("初学者");
            user.setExperience(0);
            user.setMembershipType("FREE");
            user.setAgreementVersion(request.getAgreementVersion());
            user.setCreatedAt(LocalDateTime.now());
            user.setUpdatedAt(LocalDateTime.now());
            
            // TODO: 处理邀请码逻辑
            if (request.getInviteCode() != null) {
                log.info("处理邀请码: {}", request.getInviteCode());
            }
            
            user = userRepository.save(user);
            
            // 生成JWT令牌
            String accessToken = jwtUtil.generateAccessToken(
                    user.getId().toString(), 
                    user.getPhone(), 
                    user.getMembershipType()
            );
            String refreshToken = jwtUtil.generateRefreshToken(user.getId().toString());
            
            // 缓存用户令牌
            cacheUserToken(user.getId().toString(), accessToken);
            
            // 构建响应
            UserAuthResponse.UserInfo userInfo = UserAuthResponse.UserInfo.builder()
                    .userId(user.getId().toString())
                    .phone(maskPhone(user.getPhone()))
                    .nickname(user.getNickname())
                    .avatar("")
                    .level(user.getLevel())
                    .experience(user.getExperience())
                    .membershipType(user.getMembershipType())
                    .registerTime(user.getCreatedAt())
                    .build();
            
            return UserAuthResponse.builder()
                    .userId(user.getId().toString())
                    .accessToken(accessToken)
                    .refreshToken(refreshToken)
                    .expiresIn(7200)
                    .userInfo(userInfo)
                    .build();
                    
        } catch (Exception e) {
            log.error("用户注册失败: {}", e.getMessage());
            throw new RuntimeException("注册失败: " + e.getMessage());
        }
    }
    
    @Override
    public UserAuthResponse login(UserLoginRequestV2 request) {
        try {
            User user;
            
            if ("PASSWORD".equals(request.getLoginType())) {
                // 密码登录
                user = userRepository.findByPhone(request.getPhone())
                        .orElseThrow(() -> new RuntimeException("用户不存在"));
                
                if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
                    throw new RuntimeException("密码错误");
                }
            } else if ("SMS_CODE".equals(request.getLoginType())) {
                // 验证码登录
                validateVerificationCode(request.getPhone(), "LOGIN", request.getVerificationCode());
                
                user = userRepository.findByPhone(request.getPhone())
                        .orElseThrow(() -> new RuntimeException("用户不存在"));
            } else {
                throw new RuntimeException("不支持的登录类型");
            }
            
            // 更新最后登录时间
            user.setLastLoginAt(LocalDateTime.now());
            user.setUpdatedAt(LocalDateTime.now());
            user = userRepository.save(user);
            
            // 生成JWT令牌
            String accessToken = jwtUtil.generateAccessToken(
                    user.getId().toString(), 
                    user.getPhone(), 
                    user.getMembershipType()
            );
            String refreshToken = jwtUtil.generateRefreshToken(user.getId().toString());
            
            // 缓存用户令牌
            cacheUserToken(user.getId().toString(), accessToken);
            
            // 构建响应
            UserAuthResponse.UserInfo userInfo = UserAuthResponse.UserInfo.builder()
                    .userId(user.getId().toString())
                    .phone(maskPhone(user.getPhone()))
                    .nickname(user.getNickname())
                    .avatar(user.getAvatar())
                    .level(user.getLevel())
                    .experience(user.getExperience())
                    .membershipType(user.getMembershipType())
                    .lastLoginTime(user.getLastLoginAt())
                    .build();
            
            return UserAuthResponse.builder()
                    .userId(user.getId().toString())
                    .accessToken(accessToken)
                    .refreshToken(refreshToken)
                    .expiresIn(7200)
                    .userInfo(userInfo)
                    .build();
                    
        } catch (Exception e) {
            log.error("用户登录失败: {}", e.getMessage());
            throw new RuntimeException("登录失败: " + e.getMessage());
        }
    }
    
    @Override
    public RefreshTokenResponse refreshToken(String refreshToken) {
        try {
            if (!jwtUtil.validateToken(refreshToken)) {
                throw new RuntimeException("刷新令牌无效");
            }
            
            String userId = jwtUtil.getUserIdFromToken(refreshToken);
            User user = userRepository.findById(Long.valueOf(userId))
                    .orElseThrow(() -> new RuntimeException("用户不存在"));
            
            // 生成新的访问令牌
            String newAccessToken = jwtUtil.generateAccessToken(
                    user.getId().toString(),
                    user.getPhone(),
                    user.getMembershipType()
            );
            
            // 缓存新令牌
            cacheUserToken(user.getId().toString(), newAccessToken);
            
            return RefreshTokenResponse.builder()
                    .accessToken(newAccessToken)
                    .expiresIn(7200)
                    .build();
                    
        } catch (Exception e) {
            log.error("刷新令牌失败: {}", e.getMessage());
            throw new RuntimeException("刷新令牌失败: " + e.getMessage());
        }
    }
    
    @Override
    public void logout(String accessToken, Boolean allDevices) {
        try {
            String userId = jwtUtil.getUserIdFromToken(accessToken);
            
            if (Boolean.TRUE.equals(allDevices)) {
                // 登出所有设备，清除用户所有令牌
                String userTokensKey = USER_TOKENS_PREFIX + userId;
                redisTemplate.delete(userTokensKey);
            } else {
                // 只登出当前设备，将当前令牌加入黑名单
                String blacklistKey = TOKEN_BLACKLIST_PREFIX + accessToken;
                long remainingTime = jwtUtil.getTokenRemainingTime(accessToken);
                if (remainingTime > 0) {
                    redisTemplate.opsForValue().set(blacklistKey, "1", remainingTime, TimeUnit.SECONDS);
                }
            }
            
        } catch (Exception e) {
            log.error("用户登出失败: {}", e.getMessage());
            throw new RuntimeException("登出失败: " + e.getMessage());
        }
    }
    
    @Override
    public boolean validateAccessToken(String token) {
        try {
            // 检查令牌格式和签名
            if (!jwtUtil.validateToken(token)) {
                return false;
            }
            
            // 检查是否在黑名单中
            String blacklistKey = TOKEN_BLACKLIST_PREFIX + token;
            if (redisTemplate.hasKey(blacklistKey)) {
                return false;
            }
            
            return true;
        } catch (Exception e) {
            log.debug("令牌验证失败: {}", e.getMessage());
            return false;
        }
    }
    
    @Override
    public String getUserIdFromToken(String token) {
        return jwtUtil.getUserIdFromToken(token);
    }
    
    @Override
    public boolean isVipMember(String token) {
        try {
            String membershipType = jwtUtil.getMembershipTypeFromToken(token);
            return "VIP".equals(membershipType) || "PREMIUM".equals(membershipType);
        } catch (Exception e) {
            return false;
        }
    }
    
    private void validateVerificationCode(String phone, String type, String code) {
        String codeKey = SMS_CODE_PREFIX + phone + ":" + type;
        String storedCode = redisTemplate.opsForValue().get(codeKey);
        
        if (storedCode == null) {
            throw new RuntimeException("验证码已过期");
        }
        
        if (!storedCode.equals(code)) {
            throw new RuntimeException("验证码错误");
        }
        
        // 验证成功后删除验证码
        redisTemplate.delete(codeKey);
    }
    
    private void cacheUserToken(String userId, String token) {
        try {
            String userTokensKey = USER_TOKENS_PREFIX + userId;
            redisTemplate.opsForSet().add(userTokensKey, token);
            redisTemplate.expire(userTokensKey, 30, TimeUnit.DAYS);
        } catch (Exception e) {
            log.warn("缓存用户令牌失败: {}", e.getMessage());
        }
    }
    
    private String maskPhone(String phone) {
        if (phone == null || phone.length() != 11) {
            return phone;
        }
        return phone.substring(0, 3) + "****" + phone.substring(7);
    }
}
*/